﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System;
using Extensions;

namespace TC
{
    public class ContextEditor : EditorWindow
    {
        public bool invokeParentRepaint = false;
        private Graph graph;
        private FlowGraphSurface flowGraphSurface;
        private Dictionary<string, string> tmpNames = new Dictionary<string, string>(); // key:control name; value: variable name
        private string lastControlName = "";


        private void OnGUI()
        {
            if (graph != BluePrintEditor.graph)
            {
                graph = BluePrintEditor.graph;
                flowGraphSurface = BluePrintEditor.flowGraphSurface;
            }
            if (graph == null || flowGraphSurface == null) return;

            if (lastControlName != GUI.GetNameOfFocusedControl())
            {
                tmpNames.Clear();
                for (int i = 0; i < graph.vars.Count; ++i)
                {
                    tmpNames.Add(i.ToString(), graph.vars[i].name);
                }
                lastControlName = GUI.GetNameOfFocusedControl();
            }

            List<ValueWrap> vars = graph.vars;
            EditorGUILayout.BeginVertical();
            for (int i = 0; i < vars.Count; ++i)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.BeginHorizontal();
                ValueWrap w = vars[i];

                // variable name
                if (Event.current.Equals(Event.KeyboardEvent("return")) && GUI.GetNameOfFocusedControl() == i.ToString())
                {
                    if (tmpNames[i.ToString()] != w.name)
                    {
                        if (!CheckRestriction(tmpNames[i.ToString()], w.type))
                        {
                            tmpNames[i.ToString()] = w.name;
                            EditorUtility.DisplayDialog("Warning", "Could not change type cause there already exists another variable with the same name and type.", "OK");
                        }
                        else
                        {
                            w.name = tmpNames[i.ToString()];
                            EventCenter.Instance.SendEvent<ValueWrap>((int)EventCenterNumber.OnContextNameChg, w);
                            invokeParentRepaint = true;
                        }
                    }
                }
                GUI.SetNextControlName(i.ToString());
                tmpNames[i.ToString()] = EditorGUILayout.TextField(tmpNames[i.ToString()], GUILayout.Width(150));


                // variable type
                VarType tmp = (VarType)EditorGUILayout.EnumPopup(w.type, GUILayout.Width(150));
                bool change = tmp != w.type;
                if (change)
                {
                    if (!CheckRestriction(w.name, tmp))
                    {
                        EditorUtility.DisplayDialog("Warning", "Could not change type cause there already exists another variable with the same name and type.", "OK");
                    }
                    else
                    {
                        // Graph 中有对应的Context Node时，弹出提示框
                        if (flowGraphSurface.IsContextVarUsing(w))
                        {
                            if (EditorUtility.DisplayDialog("Change Variable type",
                                "This could break connections, do you really want all Variable \'" + w.name + "\' instances change its type ?", "Yes", "No"))
                            {
                                w.type = tmp;
                                flowGraphSurface.ChangeContextNodeType();
                            }
                        }
                        else { w.type = tmp; }
                    }
                }

                switch (w.type)
                {
                    case VarType.Int:
                        w.value = EditorGUILayout.IntField(change ? 0 : (int)w.value);
                        break;
                    case VarType.Float:
                        w.value = EditorGUILayout.FloatField(change ? 0.0f : (float)w.value);
                        break;
                    case VarType.Long:
                        w.value = EditorGUILayout.LongField(change ? 0 : (long)w.value);
                        break;
                    case VarType.String:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.Bool:
                        w.value = EditorGUILayout.Toggle(change ? true : (bool)w.value);
                        break;
                    case VarType.Vector3:
                        w.value = EditorGUILayout.Vector3Field("", change ? Vector3.zero : (Vector3)w.value);
                        break;
                    case VarType.GameObject:
                        break;
                    case VarType.Blurprint:
                        break;
                    case VarType.IntArray:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.FloatArray:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.LongArray:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.StringArray:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.BoolArray:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.Vector3Array:
                        w.value = EditorGUILayout.TextField(change ? "" : w.value.ToString());
                        break;
                    case VarType.GameObjectArray:
                        break;
                    default:
                        break;
                }
                EditorGUILayout.EndHorizontal();

                // delete button
                if (GUILayout.Button("delete", GUILayout.Width(50)))
                {
                    if (flowGraphSurface.IsContextVarUsing(w))
                    {
                        if (EditorUtility.DisplayDialog("Delete Variable",
                        "This could delete all \'" + w.name + "\' instances and the context variable, do you really want to delete them?", "Yes", "No"))
                        {
                            flowGraphSurface.RemoveContextNode();
                            vars.Remove(vars[i]);
                        }
                    }
                    else { vars.Remove(vars[i]); }
                }
                EditorGUILayout.EndHorizontal();
            }

            if(GUILayout.Button("Add"))
            {
                string randomName = DateTime.UtcNow.ToString();
                vars.Add(new ValueWrap() { name = randomName, type = VarType.Int, value = 0 });
                tmpNames.Add(tmpNames.Count.ToString(), randomName);
            }
            EditorGUILayout.EndVertical();
        }

        // Context 不允许同名、同Type的变量
        public bool CheckRestriction(string aimName, VarType aimType)
        {
            foreach (var var in graph.vars)
            {
                if (var.name == aimName && var.type == aimType) { return false; }
            }
            return true;
        }

        private void OnLostFocus()
        {
            tmpNames.Clear();
            for (int i = 0; i < graph.vars.Count; ++i)
            {
                tmpNames.Add(i.ToString(), graph.vars[i].name);
            }
        }
    }
}
